/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef GIMI_SUBSCRIPTIONS_H
#define GIMI_SUBSCRIPTIONS_H

#include <map>

#include "gimiutils.h"

namespace gimi {

class GIMICore;
  
/**
 * Container for information about a subscription.
 */
struct subscriptionInfo {
  subscriptionInfo(const int uInterval);
  
  int updateInterval; ///< Timeout in ms for a re-subscription. < 1 means that re-subscription is not made automatically
  gim::time nextUpdate; ///< When subscription "timeouts" and a new should be made.
};
  
// minortype, subscription
typedef std::map< int, subscriptionInfo > t_subscriptionsMinorTypes;
typedef t_subscriptionsMinorTypes::iterator t_subscriptionsMinorTypesIterator;
typedef t_subscriptionsMinorTypes::const_iterator t_subscriptionsMinorTypesConstIterator;
typedef std::pair< int, subscriptionInfo > t_subscriptionsMinorPair;

// majortype, 
typedef std::map< int, t_subscriptionsMinorTypes > t_subscriptionsMajorTypes;
typedef t_subscriptionsMajorTypes::iterator t_subscriptionsMajorTypesIterator;
typedef t_subscriptionsMajorTypes::const_iterator t_subscriptionsMajorTypesConstIterator;
typedef std::pair< int, t_subscriptionsMinorTypes > t_subscriptionsMajorPair;

// clientid, 
typedef std::map< int, t_subscriptionsMajorTypes > t_subscriptions;
typedef t_subscriptions::iterator t_subscriptionsIterator;
typedef t_subscriptions::const_iterator t_subscriptionsConstIterator;
typedef std::pair< int, t_subscriptionsMajorTypes > t_subscriptionsPair;

/**
 * \class GIMISubscriptions
 * 
 * Internally protected with mutex.
 */
class GIMISubscriptions {
  public:
    GIMISubscriptions();
    ~GIMISubscriptions();
    
    /**
     * Adds given subscription. If subscription existed, changes to new timeoutInterval.
     * 
     * \return Always true.
     */
    bool addSubscription(const int clientId,
                         const int majorTypeId,
                         const int minorTypeId,
                         const int timeoutInterval);
    
    /**
     * Removes given subscription.
     * 
     * \return False if given subscription did not exist.
     */
    bool removeSubscription(const int clientId,
                            const int majorTypeId,
                            const int minorTypeId);

    /**
     * Checks if given type is subscribed.
     *
     * \return Boolean.
     */
    bool isSubscription(const int clientId,
                        const int majorTypeId,
                        const int minorTypeId);
    
    /**
     * Update subscription time.
     * 
     * \return False if subscription did not exist.
     */
    bool updateSubscriptionTime(const int clientId,
                                const int majorTypeId,
                                const int minorTypeId);
    
    /**
     * Checks subscriptions for timeouted subscriptions and sends a subscribe
     * if needed.
     */
    void doResubscriptions(GIMICore *gc);
    
  private:
    // Prevents use of copy constructors
    GIMISubscriptions(const GIMISubscriptions&);
    const GIMISubscriptions& operator=(const GIMISubscriptions&);
    
    t_subscriptions subscriptions;
    ownMutexHandle subscriptionMutex;
};

} // end namespace gimi

#endif // GIMI_SUBSCRIPTIONS_H
